"""
获取gBest
"""
from collections import Counter
import random
from matplotlib.pyplot import axis
import numpy as np


def getPosition(arFits, M):
    """获得当前archive集的位置 
    Params：
        arFits：对应的适应度
        M: 划分的网格大小为M*M 
    Return：
        flags: 每个粒子对应的位置, nF维映射为1维
    """
    fmin = np.min(arFits, axis=0)
    fmax = np.max(arFits, axis=0)
    grid = (fmax - fmin) / M  # 网格的长宽
    pos = np.ceil((arFits - fmin) / grid)
    nA, nF = pos.shape
    flags = np.zeros(nA)
    for dim in range(nF - 1):
        flags += (pos[:, dim] - 1) * (M ** (nF - dim - 1))
    """
    1、以2维为例，创建16个表格，其中（3/2,3/2）对应的网格的计算公式如下：
    [4 8 12 15]
    [3 7 11 14]
    [2 6 10 13]
    [1 5 9  12]
    3/2(第0列数据) -> 2
    flags = (2-1)*(4^(2-0-1)) =4
    flags = flags + 2(最后一列，即第1列)=6 
    """
    flags += pos[:, -1]
    return flags


def getGBest(pops, fits, archive, arFits, M):
    """
    1、计算Archive中优于Pj的粒子集Aj
    2、计算Aj中密度最小的粒子集Gj
    3、gj=Rand{Gj}
    Params:
        :param pops: 坐标更新后的粒子群
        :param fits:
        :param archive: 经过updateArchive和checkArchive函数进行操作后的个体
        :param arFits:
        :param M:
        :return:
    """
    # 根据密度来从archive集中选择gBest
    nPop, nChr = pops.shape
    nF = fits.shape[1]
    gBest = np.zeros((nPop, nChr))
    flags = getPosition(arFits, M)
    for i in range(nPop):
        # 1、从archive档案中中查找没有被pops[i]支配的集合
        #  下面的代码是在archive档案中查找被pops[i]支配的集合，之后进行取反操作
        isDom1 = fits[i] <= arFits
        isDom2 = fits[i] < arFits
        isDom = (np.sum(isDom1, axis=1) == nF) & (np.sum(isDom2, axis=1) >= 1)
        # 之前的isDom是指pop[i]能够支配archive的集合，这里要取反
        isDom = ~isDom
        if np.sum(isDom) == 0:
            gBest[i] = pops[i]
            continue
        elif np.sum(isDom) == 1:
            gBest[i] = archive[isDom]
            continue
        archivePop = archive[isDom]
        # 找出ai集中每个个体所处的位置
        aDomFlags = flags[isDom]

        # 统计每个网格出现的次数 
        counts = Counter(aDomFlags).most_common()
        minFlag, minCount = counts[-1]  # 出现次数最少的网格及其次数
        # 可能有多个网格的出现的次数相同，并且同样次数最小
        minFlags = [counts[i][0] for i in range(len(counts)) if counts[i][1] == minCount]
        isCh = False
        for minFlag in minFlags:
            isCh = isCh | (aDomFlags == minFlag)
        indices = np.arange(aDomFlags.shape[0])  # 索引 
        chIndices = indices[isCh]
        # 从待选集中随机选择一个 
        idx = chIndices[int(np.random.rand() * len(chIndices))]
        gBest[i] = archivePop[idx]  # 复制给相应的gBest位置上 
    return gBest


if __name__ == "__main__":
    # 向上取整 2.0
    print(np.ceil(1.3))
    # 向下取整 1.0
    print(np.floor(1.3))

    print("--------------------")
    a = [1, 4, 2, 3, 2, 3, 4, 2]
    from collections import Counter

    print(Counter(a).most_common(1))
    # [(2, 3), (4, 2), (3, 2), (1, 1)]
    print(Counter(a).most_common())
    # Counter({2: 3, 4: 2, 3: 2, 1: 1})
    print(Counter(a))

    print("----------------------")
    minCount = 1
    counts = np.array([(1, 1), (4, 1), (3, 4)])
    minFlags = [counts[i][0] for i in range(len(counts)) if counts[i][1] == minCount]
    # [1, 4]
    print(minFlags)

    print("----------------------")
    # minFlag = 4
    isCh = False
    aDomFlags = np.array([1, 4, 4, 8])
    for minFlag in minFlags:
        # temp = (aDomFlags == minFlag)
        isCh = (isCh | (aDomFlags == minFlag))
        # isCh = (isCh | temp)
    # [True  True  True False]
    print("isCh--", isCh)
    # [False  True  True False]
    print(False | np.array([False, True, True, False]))

    print("----------------------")
    chIndices = np.array([1, 2, 4, 6])
    temp = int(np.random.rand() * len(chIndices))
    result = chIndices[temp]
    # temp 2
    # result 4
    print("temp", temp)
    print("result", result)
